/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package jturbofile.net;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.Serializable;
import java.util.LinkedList;
import java.util.List;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;
import jturbofile.Config;
import jturbofile.gui.LogPanel;
import net.contrapunctus.lzma.LzmaInputStream;
import net.contrapunctus.lzma.LzmaOutputStream;
import org.apache.tools.bzip2.CBZip2InputStream;
import org.apache.tools.bzip2.CBZip2OutputStream;

/**
 *
 * @author Rolf
 */
public class Packet implements Serializable {
    public enum PacketType { FILEBEGIN, FILEPART, FILEEND, CLOSE, FILECANCEL, FILEACCEPT, FILEREJECT }
    
    private List<String> options;
    private byte[] data;
    private PacketType type;
    private String sender;
    private Config.Compression compressionType;
    
    public Packet(PacketType t) {
        type = t;
        options = new LinkedList<String>();
        data = null;
        compressionType = Config.singleton().getCompressionType();
    }
    
    public void addOption(String s) {
        options.add(s);
    }
    
    public List<String> getOptions() {
        return options;
    }
    
    public Config.Compression getCompressionType() {
        return compressionType;
    }
    
    public void setData(byte[] d) {
        try {
            if(compressionType == Config.Compression.GZIP) {
                ByteArrayOutputStream bo = new ByteArrayOutputStream();
                GZIPOutputStream gout = new GZIPOutputStream( bo );
                gout.write(d, 0, d.length);
                gout.finish();
                gout.close();
                data = bo.toByteArray();
            }
            else if(compressionType == Config.Compression.BZIP) {
                ByteArrayOutputStream bo = new ByteArrayOutputStream();
                CBZip2OutputStream bzout = new CBZip2OutputStream( bo );
                bzout.write(d, 0, d.length);
                bzout.flush();
                bzout.close();
                data = bo.toByteArray();
            }
            else if(compressionType == Config.Compression.LZMA) {
                ByteArrayOutputStream bo = new ByteArrayOutputStream();
                LzmaOutputStream lzmaout = new LzmaOutputStream( bo );
                lzmaout.write(d, 0, d.length);
                lzmaout.flush();
                lzmaout.close();
                
                data = bo.toByteArray();
            }
            else {
                data = d;
            }
        }
        catch(Exception e) {
            LogPanel.singleton().logln("Error compressing data: "+e);
        }
    }
    
    public byte[] getData() {
        try {
            if( compressionType == Config.Compression.GZIP ) {
                GZIPInputStream gin = new GZIPInputStream(new ByteArrayInputStream(data));

                ByteArrayOutputStream bo = new ByteArrayOutputStream();

                byte[] buffer = new byte[1024 * 5];
                int length = gin.read(buffer, 0, buffer.length);

                while(length != -1) {
                    bo.write(buffer, 0, length);
                    length = gin.read(buffer, 0, buffer.length);                
                }

                bo.flush();

                return bo.toByteArray();
            }
            else if( compressionType == Config.Compression.BZIP ) {
                CBZip2InputStream gin = new CBZip2InputStream(new ByteArrayInputStream(data));

                ByteArrayOutputStream bo = new ByteArrayOutputStream();

                byte[] buffer = new byte[1024 * 5];
                int length = gin.read(buffer, 0, buffer.length);

                while(length != -1) {
                    bo.write(buffer, 0, length);
                    length = gin.read(buffer, 0, buffer.length);                
                }

                bo.flush();

                return bo.toByteArray();
            }
            else if( compressionType == Config.Compression.LZMA ) {
                LzmaInputStream gin = new LzmaInputStream(new ByteArrayInputStream(data));

                ByteArrayOutputStream bo = new ByteArrayOutputStream();

                byte[] buffer = new byte[1024 * 5];
                int length = gin.read(buffer, 0, buffer.length);

                while(length != -1) {
                    bo.write(buffer, 0, length);
                    length = gin.read(buffer, 0, buffer.length);                
                }

                bo.flush();

                return bo.toByteArray();
            }
            else {
                return data;
            }
        }
        catch(Exception e) {
            LogPanel.singleton().logln("Error reading compressed data: "+e);
        }
        
        return null;
    }
    
    public PacketType getType() {
        return type;
    }
    
    public String getSender() {
        return sender;
    }
    
    public void setSender(String s) {
        sender = s;
    }
}
